#include "./GameObject.h"
#include "../../Graphics/Presentation.h"
#include <boost/lexical_cast.hpp>

namespace GameLogic {
namespace Objects {

/*
 * Znaczniki - wartosci:
 */

const int GameObject::FLAG_LEFT = 0x1;
const int GameObject::FLAG_RIGHT = 0x2;
const int GameObject::FLAG_UP = 0x4;
const int GameObject::FLAG_DOWN = 0x8;

const int GameObject::FLAG_FIRE = 0x10;

/*
 * Implementacja metod:
 */

GameObject::GameObject( IdType id, float radius, Ogre::SceneNode* scene_node, Data* data , float z ):
	radius_( radius )
,	id_( id )
,	collision_state_( csNotChecked )
,	data_( data )
,	z_( z )
,	modified_( false )
,	behaviour_changed_by_player_input_( false )
,	tile_hooks_( new Level::Tile* [ 4 ] )
,	scene_node_( 0 /*scene_node*/ )
{
	if( data == 0 )
		data_= new Data();
	//scene_node->setPosition( data->position.x, data->position.y, z );

	installGraphics();

	for( int i = 0; i < 4; ++i )
		tile_hooks_[ i ] = 0;
}

void GameObject::installGraphics() {
/*
	Graphics::Presentation& presentation = Graphics::Presentation::getInstance();
	Ogre::SceneManager* scene_manager = presentation.getSceneManager();

	Graphics::Presentation::createSphere("mesh" + boost::lexical_cast< std::string >( id_.toNumeric() ), Graphics::Presentation::toOgreCoords( getRadius() ), 12, 12);

	Ogre::Entity* entity_ = scene_manager->createEntity("Head" + boost::lexical_cast< std::string >( id_.toNumeric() ), "mesh" + boost::lexical_cast< std::string >( id_.toNumeric() ));
	scene_node_ = scene_manager->createSceneNode();
	scene_manager->getRootSceneNode()->addChild( scene_node_ );
	scene_node_->attachObject( entity_ );
*/

	Graphics::Presentation& presentation = Graphics::Presentation::getInstance();
	Ogre::SceneManager* scene_manager = presentation.getSceneManager();

	Graphics::Presentation::createSphere("mesh" + boost::lexical_cast< std::string >( id_.toNumeric() ), Graphics::Presentation::toOgreCoords( getRadius() ), 12, 12);
	Ogre::Entity* entity_ = scene_manager->createEntity("Head" + boost::lexical_cast< std::string >( id_.toNumeric() ), "mesh" + boost::lexical_cast< std::string >( id_.toNumeric() ));

	//Ogre::Entity* entity_ = scene_manager->createEntity("Head" + boost::lexical_cast< std::string >( id_.toNumeric() ), "ballfloor");

	scene_node_ = presentation.createSceneNode( entity_ );

	Graphics::Presentation::createSphere("mesh_sm" + boost::lexical_cast< std::string >( id_.toNumeric() ), Graphics::Presentation::toOgreCoords( 0.3f*getRadius() ), 12, 12);
	entity_ = scene_manager->createEntity("Arm" + boost::lexical_cast< std::string >( id_.toNumeric() ), "mesh_sm" + boost::lexical_cast< std::string >( id_.toNumeric() ));
	Ogre::SceneNode* sn = presentation.createSceneNode( entity_, scene_node_ );

	sn->translate(
			Graphics::Presentation::toOgreCoords( getRadius() ),
			0.0f, //Graphics::Presentation::toOgreCoords( getRadius() ),
			0.0f //Graphics::Presentation::toOgreCoords( getRadius() )
	);
}

GameObject::~GameObject() {
	delete [] tile_hooks_;
}

float GameObject::getWalkSpeed() {
	return DEFAULT_WALK_SPEED;
}

float GameObject::getBackwardWalkSpeed() {
	return DEFAULT_BACKWARD_WALK_SPEED;
}

float GameObject::getStrafeSpeed() {
	return DEFAULT_STRAFE_SPEED;
}

void GameObject::setFacing( const Vec2f& facing ) {
	//oblicza kat pomiedzy starym i nowym wektorem:
	float old_angle = data_->facing.angle();
	float new_angle = facing.angle();
	//...oto i on:
	float angle = new_angle - old_angle;
	//obliczony kat stanowi zmiane obrotu obiektu. Nalezy zastosowac ja
	//do zmiany obrotu modelu obiektu:
	scene_node_->yaw(Ogre::Radian( angle ));
}

void GameObject::replaceData( Data* data ) {
	delete data_;
	data_ = data;
	//wymusza to takze zmiany w parametrach modelu obiektu:
	positionOnScene();
}

void GameObject::onHit( GameObject* go ) {

}

void GameObject::onHitImpassableTile() {

}

void GameObject::positionOnScene() {
	Vec2f& pos = data_->position;
	scene_node_->setPosition(
			Graphics::Presentation::toOgreCoords( pos.x ),
			Graphics::Presentation::toOgreCoords( getZPos() ),
			Graphics::Presentation::toOgreCoords( pos.y )
	);
	Vec2f& rot = data_->facing;
	scene_node_->setDirection( rot.x, 0.0f, rot.y );
}

/* Przesuwa obiekt o wektor. */
void GameObject::translate( const Vec2f& vect ) {
	data_->position += vect;
	scene_node_->translate(
			Graphics::Presentation::toOgreCoords( vect.x ),
			0.0f,
			Graphics::Presentation::toOgreCoords( vect.y )
	);
}

} //namespace Level
} //namespace Objects
